package org.dei.perla.utils.testframework;


import java.util.*;
import org.dei.perla.parser.expressions.*;

/**
 * 
 * @author Camplani, Fortunato, Marelli, Rota, Vigano' et al.
 * Classe che descrive il singolo test su un nodo.
 *
 */
public class SingleTest {
	
	/**
	 * ArrayList contenente nell'ordine il tipo di getResultType() e di getResult()
	 */
	private ArrayList<Class<?>> pHopedResults;
	
	/**
	 * Nodo da testare
	 */
	private Node pNodeToBeTested;
	
	/**
	 * NodeEqual che viene sfruttato per testare il risultato
	 */
	private NodeEqual pNodeEqual;
	
	
	///// COSTRUTTORI
	
	
	/**
	 * Costruttore se c'è da testare un nodo, qualsiasi esso sia 
	 */
	public SingleTest(Node parNodeToTest,ArrayList<Class<?>> parHopedResults, Node parNodeCorrect) {
		
		this.pNodeToBeTested = parNodeToTest;
		this.pHopedResults = parHopedResults;
		this.pNodeEqual =  new NodeEqual(parNodeToTest,parNodeCorrect);
		
	}


	/////METODO DI ESECUZIONE TEST
	
	/**
	 * Testa getResult() e il risultato se opportuno
	 */	
	private String[] testGetResult() {
		
		String[] tResult = new String[2];
		tResult[0]="-";
		tResult[1]="-";
		
		try {
			
					
			if (this.pNodeToBeTested.getResult().getClass()==this.pHopedResults.get(1)) {
				
				tResult[0]="OK";
				
				
				//proseguo con il controllo dei risultati
				
				if (this.pNodeEqual.getSecondNode().getResult().getClass()==ConstantNull.class) {
					
					tResult[0]="OK";
					
				} else if (this.pNodeEqual.getSecondNode().getResult().getClass()==ConstantLogic.class)
					
					{
					
					if (this.pNodeEqual.getSecondNode().getResult().getValueLogic()==
						((NodeOperation)this.pNodeToBeTested).getResult().getValueLogic()) {
						
						tResult[1]= "OK";
						
					}
					else {
						
						tResult[1]= "KO, ho ottenuto "+((NodeOperation)this.pNodeToBeTested).getResult().getValueLogic();
					}
						
					
					}
				
				else if (this.pNodeEqual.getResult().getValueLogic()==LogicValue.TRUE) {
					
					tResult[1]="OK";
					
				}
				else {
					
					tResult[1]="KO";
				
				}
			}
			
			else {
				
				tResult[0]="KO, ottenuto tipo: "+this.pNodeToBeTested.getResult().getClass()+". Non testo il risultato...";
				tResult[1]="-";
				
			}
		
		} catch (ConstantCreationException e) {
			
			if (e.getClass()==this.pHopedResults.get(1)) {
				
				tResult[0]="OK";
				tResult[1]="-";
			}
			else {
				
				tResult[0]="KO, "+e.toString();
				
			}
			
		} catch (ConstantCastException e) {
			
			if (e.getClass()==this.pHopedResults.get(1)) {
				
				tResult[0]="OK";
				tResult[1]="-";
			}
			else {
				
				tResult[0]="KO, "+e.toString();				
				
			}
			
		} catch (OperationNotSupportedException e) {
			
			if (e.getClass()==this.pHopedResults.get(1)) {
				
				tResult[0]="OK";
				tResult[1]="-";
			}
			else {
				
				tResult[0]="KO, "+e.toString();			
				
			}
			
		} catch (DivisionByZeroException e) {
			
			if (e.getClass()==this.pHopedResults.get(1)) {
				
				tResult[0]="OK";
				tResult[1]="-";
			}
			else {
				
				tResult[0]="KO, "+e.toString();
					
			}
			
		}
	
	return tResult;
	}
	
	
	/**
	 * Testa getResultType() sul nodo e confronta con i risultati sperati
	 */
	private String testGetResultType() {
		
		try {
			
			if (this.pNodeToBeTested.getResultType()==this.pHopedResults.get(0)) {
				
				return "OK";
			}
			else {
				
				return "KO, "+this.pNodeToBeTested.getResultType().toString();
				
			}
			
			
		} catch (OperationNotSupportedException e) {
			
			if (e.getClass()==this.pHopedResults.get(0)) {
				
				return "OK";
			}
			else {
				
				return "KO, "+e.toString();
				
			}
			
		}
		
	}
	
	
	/**
	 * Esegue i test visualizzando i risultati
	 */
	public void test() {
		
		System.out.println("getResultType(): "+testGetResultType());
		System.out.println("getResult(): "+testGetResult()[0]);
		System.out.println("Risultato: "+testGetResult()[1]);
		
	}
	
	
}
